package com.umgsai.wx.backend.controller;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.umgsai.wx.backend.dao.SerialCodeMapper;
import com.umgsai.wx.backend.dao.data.QrsystemSerialCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@RestController
public class TestController {

	@Resource
	private SerialCodeMapper serialCodeMapper;
	@Resource(name = "commonExecutor")
	protected ThreadPoolExecutor commonExecutor;

	@RequestMapping(value = "/api/qrsystem/fixByCreateDate", method = RequestMethod.GET)
	public Object fixByCreateDate(@RequestParam(required = false, defaultValue = "false") Boolean updateData) {
		commonExecutor.execute(() -> {
			Long createDateMaxId = serialCodeMapper.queryCreateDateMaxId();
			Long createDateMinId = serialCodeMapper.queryCreateDateMinId();
			log.info("createDateMinId={}, createDateMaxId={} updateData={}", createDateMinId, createDateMaxId, updateData);
			Long index = createDateMinId;
			List<Long> createDateIdList = Lists.newArrayList();
			while (index <= createDateMaxId) {
				createDateIdList.add(index);
				index++;
				if (createDateIdList.size() >= 100) {
					processCreateDate(createDateIdList, updateData);
					createDateIdList.clear();
//                break;
				}
			}
			if (createDateIdList.size() > 0) {
				processCreateDate(createDateIdList, updateData);
			}
		});
		Map<String, Object> map = Maps.newHashMap();
		map.put("msg", "fixByCreateDate正在执行。。。");
		return map;
	}

	private void processCreateDate(List<Long> createDateIdList, Boolean updateData) {
		if (createDateIdList.size() > 0) {
			log.info("processCreateDate id={}", createDateIdList.get(0));
		}

		List<QrsystemSerialCode> qrsystemSerialCodeCreateDateList = serialCodeMapper.querySerialCodeCreateDateList(createDateIdList);
		Map<Long, QrsystemSerialCode> createDateMap = Maps.newHashMap();
		for (QrsystemSerialCode qrsystemSerialCode : qrsystemSerialCodeCreateDateList) {
			createDateMap.put(qrsystemSerialCode.getId(), qrsystemSerialCode);
		}
		List<QrsystemSerialCode> qrsystemSerialCodes = serialCodeMapper.querySerialCodeList(createDateIdList);
		Map<Long, QrsystemSerialCode> map = Maps.newHashMap();
		for (QrsystemSerialCode qrsystemSerialCode : qrsystemSerialCodes) {
			map.put(qrsystemSerialCode.getId(), qrsystemSerialCode);
		}

		List<CompletableFuture<Void>> completableFutureList = Lists.newArrayList();

		for (Long id : createDateIdList) {
			completableFutureList.add(CompletableFuture.runAsync(() -> {
				try {
					QrsystemSerialCode qrsystemSerialCodeCreateDate = createDateMap.get(id);
					QrsystemSerialCode qrsystemSerialCode = map.get(id);
					if (qrsystemSerialCodeCreateDate == null) {
						log.error("id={} qrsystemSerialCodeCreateDate is null", id);
						return;
					}
					if (qrsystemSerialCode == null) {
						log.error("id={} qrsystemSerialCode is null", id);
						return;
					}
					String lotNumberCreateDate = qrsystemSerialCodeCreateDate.getLotNumber();
					String sendOrderIdCreateDate = qrsystemSerialCodeCreateDate.getSendOrderId();

					String lotNumber = qrsystemSerialCode.getLotNumber();
					String sendOrderId = qrsystemSerialCode.getSendOrderId();

					if (StringUtils.isNotBlank(lotNumberCreateDate) && StringUtils.isBlank(lotNumber)) {
						log.warn("createDate表中lotNumber不为空，但生产表中lotNumber为空。需要更新。id={} lotNumber={}", id, lotNumberCreateDate);
						if (updateData) {
							int update = serialCodeMapper.updateLotNumber(id, lotNumberCreateDate);
							log.warn("createDate表中lotNumber不为空，但生产表中lotNumber为空。需要更新。id={} lotNumber={} update={}", id, lotNumberCreateDate, update);
						}
					}

					if (StringUtils.isNotBlank(sendOrderIdCreateDate) && StringUtils.isBlank(sendOrderId)) {
						log.warn("createDate表中sendOrderId不为空，但生产表中sendOrderId为空。需要更新。id={} sendOrderId={}", id, sendOrderIdCreateDate);
						if (updateData) {
							int update = serialCodeMapper.updateSendOrderId(id, sendOrderIdCreateDate);
							log.warn("createDate表中sendOrderId不为空，但生产表中sendOrderId为空。需要更新。id={} sendOrderId={} update={}", id, sendOrderIdCreateDate, update);
						}
					}
				} catch (Exception e) {
					log.error("exception", e);
				}
			}, commonExecutor));
		}

		CompletableFuture<Void>[] futureArray = new CompletableFuture[completableFutureList.size()];
		CompletableFuture.allOf(completableFutureList.toArray(futureArray)).join();
	}


	@RequestMapping(value = "/api/qrsystem/fixByUpdateDate", method = RequestMethod.GET)
	public Object fixByUpdateDate(@RequestParam(required = false, defaultValue = "false") Boolean updateData) {
		commonExecutor.execute(() -> {
			Long updateDateMaxId = serialCodeMapper.queryUpdateDateMaxId();
			Long updateDateMinId = serialCodeMapper.queryUpdateDateMinId();
			log.info("updateDateMinId={}, updateDateMaxId={} updateData={}", updateDateMinId, updateDateMaxId, updateData);
			Long index = updateDateMinId;
			List<Long> updateDateIdList = Lists.newArrayList();
			while (index <= updateDateMaxId) {
				updateDateIdList.add(index);
				index++;
				if (updateDateIdList.size() >= 100) {
					processUpdateDate(updateDateIdList, updateData);
					updateDateIdList.clear();
//                break;
				}
			}
			if (updateDateIdList.size() > 0) {
				processUpdateDate(updateDateIdList, updateData);
			}
		});
		Map<String, Object> map = Maps.newHashMap();
		map.put("msg", "fixByUpdateDate正在执行。。。【2021年1月1日-2021年6月30日】");
		return map;
	}

	private void processUpdateDate(List<Long> createDateIdList, Boolean updateData) {
		if (createDateIdList.size() > 0) {
			log.info("【2021年1月1日-2021年6月30日】 processUpdateDate id={}", createDateIdList.get(0));
		}
		List<QrsystemSerialCode> qrsystemSerialCodeUpdateDateList = serialCodeMapper.querySerialCodeUpdateDateList(createDateIdList);
		if (CollectionUtils.isEmpty(qrsystemSerialCodeUpdateDateList)) {
			log.info("【2021年1月1日-2021年6月30日】 updateDate表中无当前批次记录，跳过。。。");
			return;
		}
		Map<Long, QrsystemSerialCode> updateDateMap = Maps.newHashMap();
		for (QrsystemSerialCode qrsystemSerialCode : qrsystemSerialCodeUpdateDateList) {
			updateDateMap.put(qrsystemSerialCode.getId(), qrsystemSerialCode);
		}
		List<QrsystemSerialCode> qrsystemSerialCodes = serialCodeMapper.querySerialCodeList(createDateIdList);
		Map<Long, QrsystemSerialCode> map = Maps.newHashMap();
		for (QrsystemSerialCode qrsystemSerialCode : qrsystemSerialCodes) {
			map.put(qrsystemSerialCode.getId(), qrsystemSerialCode);
		}

		if (qrsystemSerialCodeUpdateDateList.size() == 0 && qrsystemSerialCodes.size() == 0) {
			return;
		}

		List<CompletableFuture<Void>> completableFutureList = Lists.newArrayList();

		for (Long id : createDateIdList) {
			completableFutureList.add(CompletableFuture.runAsync(() -> {
				try {
					QrsystemSerialCode qrsystemSerialCodeUpdateDate = updateDateMap.get(id);
					QrsystemSerialCode qrsystemSerialCode = map.get(id);
					if (qrsystemSerialCodeUpdateDate == null) {
//                        log.info("id={} qrsystemSerialCodeUpdateDate is null", id);
						return;
					}
					if (qrsystemSerialCode == null) {
//                        log.info("id={} qrsystemSerialCode is null", id);
						return;
					}
					String lotNumberUpdateDate = qrsystemSerialCodeUpdateDate.getLotNumber();
					String sendOrderIdUpdateDate = qrsystemSerialCodeUpdateDate.getSendOrderId();

					String lotNumber = qrsystemSerialCode.getLotNumber();
					String sendOrderId = qrsystemSerialCode.getSendOrderId();

					if (StringUtils.isNotBlank(lotNumberUpdateDate) && StringUtils.isBlank(lotNumber)) {
						log.warn("【2021年1月1日-2021年6月30日】updateDate表中lotNumber不为空，但生产表中lotNumber为空。需要更新。id={} lotNumber={}", id, lotNumberUpdateDate);
						if (updateData) {
							int update = serialCodeMapper.updateLotNumber(id, lotNumberUpdateDate);
							log.warn("【2021年1月1日-2021年6月30日】updateDate表中lotNumber不为空，但生产表中lotNumber为空。需要更新。id={} lotNumber={} update={}", id, lotNumberUpdateDate, update);
						}
					}

					if (StringUtils.isNotBlank(sendOrderIdUpdateDate) && StringUtils.isBlank(sendOrderId)) {
						log.warn("【2021年1月1日-2021年6月30日】updateDate表中sendOrderId不为空，但生产表中sendOrderId为空。需要更新。id={} sendOrderId={}", id, sendOrderIdUpdateDate);
						if (updateData) {
							int update = serialCodeMapper.updateSendOrderId(id, sendOrderIdUpdateDate);
							log.warn("【2021年1月1日-2021年6月30日】updateDate表中sendOrderId不为空，但生产表中sendOrderId为空。需要更新。id={} sendOrderId={} update={}", id, sendOrderIdUpdateDate, update);
						}
					}
				} catch (Exception e) {
					log.error("exception", e);
				}
			}, commonExecutor));
		}
		CompletableFuture<Void>[] futureArray = new CompletableFuture[completableFutureList.size()];
		CompletableFuture.allOf(completableFutureList.toArray(futureArray)).join();
	}

	@RequestMapping(value = "/api/test")
	public Object test(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
		Map<String, Object> map = Maps.newHashMap();
		map.put("msg", "this is a test");

//		Map<String, String> headerMap = Maps.newHashMap();
		Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String headerName = (String) headerNames.nextElement();
//			headerMap.put(headerName, httpServletRequest.getHeader(headerName));
			log.info("{} : {}", headerName, httpServletRequest.getHeader(headerName));
		}

		log.info(getPostData(httpServletRequest));

		httpServletResponse.setHeader("header1", "value1");
		httpServletResponse.setStatus(202);

		return map;
	}

	private String getPostData(HttpServletRequest request) {
		StringBuilder data = new StringBuilder();
		String line;
		BufferedReader reader;
		try {
			reader = request.getReader();
			while (null != (line = reader.readLine())) {
				data.append(line);
			}
		} catch (IOException e) {
			log.error("getPostData error.", e);
		}
		return data.toString();
	}
}
